﻿// Copyright (c) 2013, Simon Carter.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted 
// provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list of 
//   conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice, this list of 
//  conditions and the following disclaimer in the documentation and/or other materials provided 
//  with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// History
// Initial Release - Simon Carter
//

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Drawing.Printing;

using TCPMessageServer;

using ErrorManager.Console.Controls;
using ErrorManager.Console.Classes;

namespace ErrorManager.Console
{
    public partial class ErrorServerConsoleForm : Form
    {
        #region Constants

        private const string CONST_NUMERIC = "0123456789";

        #endregion Constants

        #region Private Members

        private MessageClient _client;
        private string _userName;
        private string _password;
        private bool _closing = false;
        private bool _imageRetrieved = false;
        private bool _saving = false;
        private int _printPage = 0;
        private List<TabPage> _dynamicTabs;

        #endregion Private Members

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        public ErrorServerConsoleForm()
        {
            _dynamicTabs = new List<TabPage>();
            InitializeComponent();
            UpdateUI(false);
            LoadSettings();
            ClearErrorInfo();
            UnloadUserDetails();
        }

        #endregion Constructors

        #region Properties

        #region User Settings

        /// <summary>
        /// If true a message is displayed to confirm error has deleted
        /// </summary>
        public bool ConfirmErrorDeleted { get; set; }

        /// <summary>
        /// if true when the user connects the first error in the list is shown
        /// </summary>
        public bool LoadErrorWhenConnected { get; set; }

        /// <summary>
        /// If true a message is displayed to confirm the error has been saved
        /// </summary>
        public bool ConfirmFileSaved { get; set; }

        #endregion User Settings

        #region Error Properties

        /// <summary>
        /// Returns the number of errors
        /// </summary>
        private int ErrorCount
        {
            get
            {
                return (toolStripComboBoxErrors.Items.Count);
            }
        }

        /// <summary>
        /// Returns the current Error Index
        /// </summary>
        private int CurrentErrorIndex
        {
            get
            {
                return (toolStripComboBoxErrors.SelectedIndex);
            }
        }

        /// <summary>
        /// Determines wether an error is selected
        /// </summary>
        private bool ErrorSelected
        {
            get
            {
                return (toolStripComboBoxErrors.SelectedIndex > -1);
            }
        }

        /// <summary>
        /// Returns the active error 
        /// </summary>
        private int CurrentError
        {
            get
            {
                return (Convert.ToInt32(toolStripComboBoxErrors.SelectedItem));
            }
        }

        #endregion Error Properties

        #endregion Properties

        #region Private Methods

        /// <summary>
        /// Loads Tabs within the console
        /// </summary>
        private void LoadTabs()
        {
            LoadTab(new UserManagement());
            LoadTab(new ServerConfiguration());
        }

        /// <summary>
        /// Loads logged in user details
        /// </summary>
        private void LoadUserDetails()
        {
            toolStripStatusLabelCurrentUser.Text = String.Format("Current User: {0}", _userName);
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_COUNT"));
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERRORS_GET"));
        }

        /// <summary>
        /// Clears user information (logged out)
        /// </summary>
        private void UnloadUserDetails()
        {
            toolStripStatusLabelServer.Text = String.Format("Server: {0}", "Not Connected");
            toolStripStatusLabelCurrentUser.Text = "Current User: Not Logged In";
            toolStripStatusLabelErrorCount.Text = "Errors: Unknown";
        }

        /// <summary>
        /// Removes dynamic tabs 
        /// </summary>
        private void UnloadDynamicTabs()
        {
            foreach (TabPage page in _dynamicTabs)
            {
                tabControlConsole.TabPages.Remove(page);
            }

            _dynamicTabs.Clear();
        }

        /// <summary>
        /// Updates the UI depending on logged in state
        /// </summary>
        /// <param name="loggedIn">Indicates wether the user is logged in or not</param>
        private void UpdateUI(bool loggedIn)
        {
            serverLogOutToolStripMenuItem.Enabled = loggedIn;
            serverLoginToolStripMenuItem.Enabled = !loggedIn;
            errorToolStripMenuItem.Enabled = loggedIn;

            if (!loggedIn)
            {
                txtUserErrorInformation.Text = String.Empty;
                txtUserErrorExtraInformation.Text = String.Empty;
                toolStripComboBoxErrors.Items.Clear();
                toolStripButtonRefresh.Enabled = false;
                toolStripButtonShowImage.Enabled = false;
                toolStripButtonNextError.Enabled = false;
                toolStripButtonPreviousError.Enabled = false;
                toolStripStatusLabelCurrentError.Text = String.Empty;
                toolStripComboBoxErrors.Enabled = false;
                toolStripButtonDeleteError.Enabled = false;
                toolStripButtonIgnoreError.Enabled = false;
                toolStripButtonSaveError.Enabled = false;
                toolStripButtonPrintError.Enabled = false;
            }
            else
            {
                toolStripButtonRefresh.Enabled = true;
                toolStripComboBoxErrors.Enabled = true;

                bool errSelected = ErrorSelected;

                errorDeleteToolStripMenuItem.Enabled = errSelected;
                errorSaveToolStripMenuItem1.Enabled = errSelected;
                errorIgnoreToolStripMenuItem.Enabled = errSelected;
                errorPrintToolStripMenuItem.Enabled = errSelected;
                errorShowImageToolStripMenuItem.Enabled = errSelected;
                toolStripButtonDeleteError.Enabled = errSelected;
                toolStripButtonIgnoreError.Enabled = errSelected;
                toolStripButtonSaveError.Enabled = errSelected;
                toolStripButtonPrintError.Enabled = errSelected;
                toolStripButtonShowImage.Enabled = errSelected;

                if (errSelected)
                {
                    toolStripButtonPreviousError.Enabled = CurrentErrorIndex > 0;
                    toolStripButtonNextError.Enabled = CurrentErrorIndex < (ErrorCount -1);
                }
                else
                {
                    toolStripButtonNextError.Enabled = CurrentErrorIndex < (ErrorCount - 1);
                    toolStripButtonPreviousError.Enabled = false;
                }

                if (CurrentErrorIndex == -1)
                    toolStripStatusLabelCurrentError.Text = String.Empty;
                else
                    toolStripStatusLabelCurrentError.Text = String.Format("Current Error: {0} of {1}", CurrentErrorIndex + 1, ErrorCount);
            }
        }

        #region Form Settings

        /// <summary>
        /// Retrieves an XML Value from the configuration file
        /// </summary>
        /// <param name="root">Root in xml file</param>
        /// <param name="searchTerm">Node</param>
        /// <param name="defaultValue">Default Value if not found</param>
        /// <returns></returns>
        public string GetXMLValue(string root, string searchTerm, string defaultValue = "")
        {
            string Result = String.Empty;

            //Load xml
            XDocument xdoc = XDocument.Load("ErrorServerConfig.xml");

            //Run query
            var lv1s = from lv1 in xdoc.Descendants(root)
                       select new
                       {
                           Header = lv1.Elements(searchTerm).ToString(),
                           Children = lv1.Descendants(searchTerm)
                       };

            //Loop through results
            foreach (var lv1 in lv1s)
            {
                foreach (var lv2 in lv1.Children)
                    Result = lv2.Value;
            }

            return (String.IsNullOrEmpty(Result) ? defaultValue : Result);
        }

        /// <summary>
        /// Loads form settings
        /// </summary>
        private void LoadSettings()
        {
            this.Width = Convert.ToInt32(GetXMLValue("ErrorConsoleWidth", this.Width.ToString()));
            this.Height = Convert.ToInt32(GetXMLValue("ErrorConsoleHeight", this.Height.ToString()));

            int value = Convert.ToInt32(GetXMLValue("ErrorConsoleLeft", this.Left.ToString()));
            this.Left = value < 0 ? 0 : value;

            value = Convert.ToInt32(GetXMLValue("ErrorConsoleTop", this.Top.ToString()));
            this.Top = value < 0 ? 0 : value;

            LoadErrorWhenConnected = Convert.ToBoolean(GetXMLValue("LoadErrorWhenConnected", true.ToString()));
            ConfirmErrorDeleted = Convert.ToBoolean(GetXMLValue("ConfirmErrorDeleted", true.ToString()));
            ConfirmFileSaved = Convert.ToBoolean(GetXMLValue("ConfirmFileSaved", true.ToString()));
        }

        /// <summary>
        /// Saves Form Settings
        /// </summary>
        private void SaveSettings()
        {
            if (this.WindowState == FormWindowState.Normal)
            {
                SetXMLValue("ErrorConsoleWidth", this.Width.ToString());
                SetXMLValue("ErrorConsoleHeight", this.Height.ToString());
                SetXMLValue("ErrorConsoleLeft", this.Left.ToString());
                SetXMLValue("ErrorConsoleTop", this.Top.ToString());
            }

            SetXMLValue("ConfirmFileSaved", ConfirmFileSaved.ToString());
            SetXMLValue("LoadErrorWhenConnected", LoadErrorWhenConnected.ToString());
            SetXMLValue("ConfirmErrorDeleted", ConfirmErrorDeleted.ToString());
        }

        #endregion Form Settings

        /// <summary>
        /// Loads a list of errors
        /// </summary>
        /// <param name="errors">list of errors</param>
        private void LoadErrors(string[] errors)
        {
            toolStripComboBoxErrors.Items.Clear();

            foreach (string s in errors)
            {
                if (s != String.Empty)
                    toolStripComboBoxErrors.Items.Add(s);
            }

            if (LoadErrorWhenConnected && ErrorCount > 0)
                toolStripComboBoxErrors.SelectedIndex = 0;

            toolStripStatusLabelErrorCount.Text = String.Format("Errors: {0}", toolStripComboBoxErrors.Items.Count);
        }

        /// <summary>
        /// Loads individual Tabs within the console
        /// </summary>
        /// <param name="control"></param>
        private void LoadTab(BaseControlClass control)
        {
            // Does the control rely on an individual permission?
            if (control.Permission != String.Empty)
            {
                string message = String.Format("{0}${1}$", control.ToString(), control.Permission);
                _client.SendMessage(new TCPMessageServer.Message("PERMISSION", message, MessageType.Command));
            }
        }

        private void CreateClient(string Server, int Port)
        {
            _client = new MessageClient(Server, Port);
            _client.ClientLogin += _client_ClientLogin;
            _client.ClientLoginFailed += _client_ClientLoginFailed;
            _client.ClientLoginSuccess += _client_ClientLoginSuccess;
            _client.OnError += _client_OnError;
            _client.MessageReceived += _client_MessageReceived;
            _client.Connected += _client_Connected;
            _client.Disconnected += _client_Disconnected;
            _client.ConnectionRefused += _client_ConnectionRefused;
            _client.ClientIDChanged += _client_ClientIDChanged;
            _client.FileReceived += _client_FileReceived;
            _client.FileReceive += _client_FileReceive;
        }

        #region Client Events

        void _client_FileReceive(object sender, TransferFileEventArgs e)
        {
            e.FileName = "errorimage.gif";
        }

        void _client_FileReceived(object sender, TransferFileEventArgs e)
        {
            if (this.InvokeRequired)
            {
                FileReceivedHandler frh = new FileReceivedHandler(_client_FileReceived);
                this.Invoke(frh, new object[] { sender, e });
            }
            else
            {
                if (!_saving)
                    System.Diagnostics.Process.Start("errorimage.gif");

                _imageRetrieved = true;
                this.Cursor = Cursors.Default;
            }
        }

        void _client_ClientIDChanged(object sender, EventArgs e)
        {
        }

        void _client_ConnectionRefused(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                EventHandler ph = new EventHandler(_client_Connected);
                this.Invoke(ph, new object[] { sender, e });
            }
            else
            {
                toolStripStatusLabelCurrentUser.Text = String.Format("Not Connected", _userName);
                UnloadUserDetails();
                UpdateUI(false);
            }
        }

        void _client_Disconnected(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                EventHandler ph = new EventHandler(_client_ClientLoginFailed);
                this.Invoke(ph, new object[] { sender, e });

            }
            else
            {
                if (!_closing)
                {
                    UnloadDynamicTabs();
                    UnloadUserDetails();
                    UpdateUI(false);
                }
            }
        }

        void _client_Connected(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                EventHandler ph = new EventHandler(_client_Connected);
                this.Invoke(ph, new object[] { sender, e });
            }
            else
            {
                toolStripStatusLabelServer.Text = String.Format("Server: {0}", _client.Server);
                UpdateUI(true);
            }
        }

        void _client_MessageReceived(object sender, TCPMessageServer.Message message)
        {
            if (this.InvokeRequired)
            {
                MessageReceivedEventHandler eh = new MessageReceivedEventHandler(_client_MessageReceived);
                this.Invoke(eh, new object[] { sender, message });
            }
            else
            {
                switch (message.Type)
                {
                    case MessageType.Command:
                        ProcessCommand(message);

                        break;
                    case MessageType.Acknowledge:
                        ProcessAcknowledge(message);

                        break;
                    case MessageType.User:
                        if (MessageBox.Show(this, message.Contents + "\n\nWould you like to refresh the list of errors?", "New Error", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.Yes)
                            refreshToolStripMenuItem_Click(sender, EventArgs.Empty);

                        break;
                }
            }
        }

        void _client_OnError(object sender, TCPMessageServer.ErrorEventArgs e)
        {
            MessageBox.Show(e.Error.Message);
            this.Cursor = Cursors.Arrow;
            e.Continue = true;
        }

        void _client_ClientLoginFailed(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                EventHandler ph = new EventHandler(_client_ClientLoginFailed);
                this.Invoke(ph, new object[] { sender, e });
            }
            else
            {
                UnloadUserDetails();
                Login();
            }
        }

        void _client_ClientLogin(object sender, ClientLoginArgs e)
        {
            e.Username = _userName;
            e.Password = _password;
        }

        void _client_ClientLoginSuccess(object sender, EventArgs e)
        {
            //logged in

            if (this.InvokeRequired)
            {
                EventHandler ph = new EventHandler(_client_ClientLoginSuccess);
                this.Invoke(ph, new object[] { sender, e });
            }
            else
            {
                LoadTabs();
                LoadUserDetails();
            }
        }

        #endregion Client Events

        #region Message Processing

        /// <summary>
        /// Processes Acknowledgement Messages sent from the server
        /// </summary>
        /// <param name="message">Message to process</param>
        private void ProcessAcknowledge(TCPMessageServer.Message message)
        {
            int idx = CurrentErrorIndex; 
            
            switch (message.Title)
            {
                case "USER_ERROR_DELETE":
                    toolStripComboBoxErrors.Items.Remove(message.Contents);
                    toolStripStatusLabelErrorCount.Text = String.Format("Errors: {0}", toolStripComboBoxErrors.Items.Count);
                    ClearErrorInfo();

                    LoadError(idx);
                    
                    if (ConfirmErrorDeleted)
                        MessageBox.Show(this, String.Format("Error {0} has been deleted.", message.Contents), "Error Deleted", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    break;
                case "USER_ERROR_IGNORE":
                    toolStripComboBoxErrors.Items.Remove(message.Contents);
                    toolStripStatusLabelErrorCount.Text = String.Format("Errors: {0}", toolStripComboBoxErrors.Items.Count);
                    ClearErrorInfo();
                    LoadError(idx);

                    break;
            }
        }

        private void tabPage_Resize(object sender, EventArgs e)
        {
            //resize  all tab controls
            if (sender.GetType() == typeof(TabPage))
            {
                TabPage page = (TabPage)sender;

                foreach (Control ctl in page.Controls)
                {
                    ctl.Left = 6;
                    ctl.Top = 6;
                    ctl.Width = page.Width - 12;
                    ctl.Height = page.Height - 12;
                }
            }
        }

        public delegate void ProcessMessageEventHandler(TCPMessageServer.Message message);

        /// <summary>
        /// Processes Command Messages sent from the server
        /// </summary>
        /// <param name="message">Message to process</param>
        private void ProcessCommand(TCPMessageServer.Message message)
        {
            switch (message.Title)
            {
                case "PERMISSION": //Permissions
                    string[] parameters = message.Contents.Split('$');

                    if (parameters[2] == "True")
                    {
                        Type trp = Type.GetType(parameters[0]);
                        BaseControlClass dc = (BaseControlClass)Activator.CreateInstance(trp);

                        //add the new tab page
                        TabPage newPage = new TabPage(dc.TabName);
                        _dynamicTabs.Add(newPage);
                        tabControlConsole.TabPages.Add(newPage);
                        newPage.Controls.Add(dc);
                        newPage.Resize += tabPage_Resize;

                        //resize on the tabs
                        dc.Left = 6;
                        dc.Top = 6;
                        dc.Width = newPage.Width - 12;
                        dc.Height = newPage.Height - 12;

                        //initialise the tab
                        dc.Initialise(_client);
                    }

                    this.Cursor = Cursors.Arrow;

                    break;
                case "USER_ERROR_COUNT": // highest error number
                    toolStripStatusLabelErrorCount.Text = String.Format("Errors: {0}", message.Contents);

                    break;

                case "USER_ERRORS_GET": // list of errors
                    LoadErrors(message.Contents.Split('$'));
                    this.Cursor = Cursors.Default;

                    break;

                case "USER_ERROR_SEND_EXTRA_ERROR_DATA":
                    txtUserErrorExtraInformation.Text = message.Contents;

                    break;

                case "USER_ERROR_SEND_ERROR_DATA":
                    txtUserErrorInformation.Text = message.Contents;

                    break;
                case "USER_ERROR_HAS_IMAGE":
                    errorShowImageToolStripMenuItem.Enabled = Convert.ToBoolean(message.Contents);
                    toolStripButtonShowImage.Enabled = Convert.ToBoolean(message.Contents);
                    this.Cursor = Cursors.Arrow;

                    break;

                case "USER_ERROR_GET_IMAGE":
                    _client.ReceiveFile(message.Contents);

                    break;
            }

            UpdateUI(true);

        }

        #endregion Message Processing

        #region UI Methods

        /// <summary>
        /// Clears individual error information from the console
        /// </summary>
        private void ClearErrorInfo()
        {
            txtUserErrorInformation.Text = "";
            txtUserErrorExtraInformation.Text = "";

            errorShowImageToolStripMenuItem.Enabled = false;
            errorSaveToolStripMenuItem1.Enabled = false;
            errorDeleteToolStripMenuItem.Enabled = false;
            errorIgnoreToolStripMenuItem.Enabled = false;
            errorPrintToolStripMenuItem.Enabled = false;
        }

        /// <summary>
        /// Logs the current user out
        /// </summary>
        private void Logout()
        {
            if (_client != null && _client.IsConnected)
                _client.StopListening();

            UpdateUI(false);
        }

        /// <summary>
        /// Logs the current user in
        /// </summary>
        private void Login()
        {
            LoginForm frm = new LoginForm();

            if (frm.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                CreateClient(frm.txtServer.Text, Convert.ToInt32(frm.txtPort.Text));
                _userName = frm.txtUserName.Text;
                _password = frm.txtPassword.Text;
                _client.StartListening();
                this.Cursor = Cursors.WaitCursor;
            }
            else
            {
                Logout();
            }
        }

        #endregion UI Methods

        #region Error Management Methods

        /// <summary>
        /// Loads an error
        /// </summary>
        /// <param name="index">Index of error to load</param>
        private void LoadError(int index)
        {
            toolStripComboBoxErrors.SelectedIndex = index > (toolStripComboBoxErrors.Items.Count -1) ? -1 : index;
            UpdateUI(true);
        }

        #endregion Error Management Methods

        #region Form Events

        private void ErrorServerConsoleForm_CursorChanged(object sender, EventArgs e)
        {
            txtUserErrorExtraInformation.Cursor = this.Cursor;
            txtUserErrorInformation.Cursor = this.Cursor;
        }

        private void ErrorServerConsoleForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            _closing = true;

            if (_client != null)
                _client.StopListening();

            SaveSettings();
        }

        private void ErrorServerConsoleForm_Shown(object sender, EventArgs e)
        {
            //Show login when initially starts
            Login();
        }

        #endregion Form Events

        #endregion Private Methods

        #region Menu Items

        #region Server Menu

        private void loginToolStripMenuItem3_Click(object sender, EventArgs e)
        {
            Login();
        }

        private void serverLogOuttoolStripMenuItem_Click(object sender, EventArgs e)
        {
            Logout();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        #endregion Server Menu

        #region Error Menu

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(this, "Are you sure you want to delete the current error?", "Delete Error", MessageBoxButtons.YesNo, MessageBoxIcon.Stop) == System.Windows.Forms.DialogResult.Yes)
                _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_DELETE", toolStripComboBoxErrors.SelectedItem.ToString()));
        }

        private void ignoreToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_IGNORE", toolStripComboBoxErrors.SelectedItem.ToString()));
        }

        private void showImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_GET_IMAGE", toolStripComboBoxErrors.SelectedItem.ToString()));
        }

        private void saveToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            _saving = true;
            try
            {
                if (folderBrowserDialog1.ShowDialog(this) == DialogResult.OK)
                {
                    if (toolStripButtonShowImage.Enabled)
                    {
                        this.Cursor = Cursors.WaitCursor;
                        _imageRetrieved = false;

                        // get the latest image
                        _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_GET_IMAGE", toolStripComboBoxErrors.SelectedItem.ToString()));

                        // wait for the iamge to be retrieved
                        while (!_imageRetrieved)
                            Application.DoEvents();

                        //copy image
                        File.Copy("errorimage.gif", String.Format("{0}\\{1}.gif", folderBrowserDialog1.SelectedPath, CurrentError.ToString()), true);
                    }

                    SaveToFile(String.Format("{0}\\{1}.txt", folderBrowserDialog1.SelectedPath, CurrentError.ToString()), txtUserErrorInformation.Text);
                    SaveToFile(String.Format("{0}\\{1}.Extra.txt", folderBrowserDialog1.SelectedPath, CurrentError.ToString()), txtUserErrorInformation.Text);

                    if (ConfirmFileSaved)
                        MessageBox.Show("Error details have been saved", "Save Error Details");
                }
            }
            finally
            {
                _saving = false;
            }
        }

        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (printDialog1.ShowDialog(this) == DialogResult.OK)
            {
                _printPage = 0;

                PrintDocument printDocument = new PrintDocument();
                printDocument.PrinterSettings = printDialog1.PrinterSettings;
                printDocument.PrintPage += PrintDocumentOnPrintPage;
                printDocument.Print();
            }
        }

        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            ClearErrorInfo();
            toolStripComboBoxErrors.Items.Clear();
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERRORS_GET"));
        }

        #endregion Error Menu

        #region Edit Menu

        private void editToolStripMenuItem_Click(object sender, EventArgs e)
        {

            if (this.ActiveControl is TextBox)
            {
                TextBox tb = (TextBox)this.ActiveControl;

                editCopyToolStripMenuItem.Enabled = tb.CanSelect && tb.SelectedText.Length > 0;
                editCutToolStripMenuItem.Enabled = !tb.ReadOnly && tb.CanSelect && tb.SelectedText.Length > 0;
                editPasteToolStripMenuItem.Enabled = !tb.ReadOnly && Clipboard.ContainsText();
                editSelectAllToolStripMenuItem.Enabled = true;
                editUndoToolStripMenuItem.Enabled = !tb.ReadOnly && tb.CanUndo;
            }
            else
            {
                editCopyToolStripMenuItem.Enabled = false;
                editCutToolStripMenuItem.Enabled = false;
                editPasteToolStripMenuItem.Enabled = false;
                editSelectAllToolStripMenuItem.Enabled = false;
                editUndoToolStripMenuItem.Enabled = false;
            }
        }

        private void editUndoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.ActiveControl is TextBox)
            {
                TextBox tb = (TextBox)this.ActiveControl;

                if (tb.CanUndo)
                    tb.Undo();
            }
        }

        private void editCutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.ActiveControl is TextBox)
            {
                TextBox tb = (TextBox)this.ActiveControl;

                if (tb.CanSelect && tb.SelectedText.Length > 0)
                    tb.Cut();
            }
        }

        private void editCopyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.ActiveControl is TextBox)
            {
                TextBox tb = (TextBox)this.ActiveControl;

                if (tb.CanSelect && tb.SelectedText.Length > 0)
                    tb.Copy();
            }
        }

        private void editPasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.ActiveControl is TextBox)
            {
                TextBox tb = (TextBox)this.ActiveControl;

                if (tb.CanSelect && Clipboard.ContainsText())
                    tb.Paste();
            }
        }

        private void editSelectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.ActiveControl is TextBox)
            {
                TextBox tb = (TextBox)this.ActiveControl;

                if (tb.CanSelect)
                    tb.SelectAll();
            }
        }

        #endregion Edit Menu

        #region Tools Menu

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UserSettings.ShowSettings(this);
        }

        #endregion Tools Menu

        #region Help Menu

        private void helpWebsiteToolStripMenuItem3_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("https://errormanager.codeplex.com/");
        }

        private void helpAboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string AboutText = String.Format("{0}\n\n{1}\n{2}\nVersion: {3}\n{4}\n{5}",
                AssemblyInfo.Configuration, AssemblyInfo.Product, Application.CompanyName, 
                Application.ProductVersion, AssemblyInfo.Copyright, 
                _client == null ? String.Empty : String.Format("Client ID: {0}", _client.ClientID));

            MessageBox.Show(AboutText, "About", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #endregion Help Menu

        #endregion Menu Items

        #region Static Methods

        /// <summary>
        /// Updates a user property value
        /// </summary>
        /// <param name="userName">Name of user</param>
        /// <param name="property">Property to be updated</param>
        /// <param name="value">New Value of property</param>
        internal static void SetXMLValue(string property, object value)
        {
            XDocument xdoc = null;

            if (System.IO.File.Exists("ErrorManager.Console.Config.xml"))
                xdoc = XDocument.Load("ErrorManager.Console.Config.xml");
            else
                xdoc = new XDocument(new XElement("Console", new XElement("Settings")));

            try
            {
                xdoc.Descendants("Settings")
                    .Single().SetElementValue(property, value);
            }
            catch (Exception err)
            {
                if (err.Message.Contains("Sequence contains no elements"))
                {
                    //if not found...

                    XElement root = xdoc.Root.Element("Settings");

                    root.Add(new XElement(property, value));
                }
                else
                    throw;
            }

            xdoc.Save("ErrorManager.Console.Config.xml");
        }

        /// <summary>
        /// Retrieves an XML Value
        /// </summary>
        /// <param name="ParentName"></param>
        /// <param name="KeyName"></param>
        /// <returns></returns>
        internal static string GetXMLValue(string property, string defaultValue = "")
        {
            if (System.IO.File.Exists("ErrorManager.Console.Config.xml"))
            {
                XDocument xdoc = XDocument.Load("ErrorManager.Console.Config.xml");

                try
                {
                    var Result = xdoc.Root.Element("Settings").Elements(property).SingleOrDefault().Value;
                    return (Result);
                }
                catch
                {
                    return (defaultValue);
                }
            }
            else
            {
                return (defaultValue);
            }
        }

        #endregion Static Methods

        #region Toolbar Methods

        private void toolStripButtonPreviousError_Click(object sender, EventArgs e)
        {
            toolStripComboBoxErrors.SelectedIndex = CurrentErrorIndex -1;
            UpdateUI(true);
        }

        private void toolStripButtonNextError_Click(object sender, EventArgs e)
        {
            toolStripComboBoxErrors.SelectedIndex = CurrentErrorIndex + 1;
            UpdateUI(true);
        }

        private void toolStripComboBoxErrors_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Occurs when user selects a new error from the drop down list
            this.Cursor = Cursors.WaitCursor;
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_SEND_ERROR_DATA", toolStripComboBoxErrors.SelectedItem.ToString()));
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_SEND_EXTRA_ERROR_DATA", toolStripComboBoxErrors.SelectedItem.ToString()));
            _client.SendMessage(TCPMessageServer.Message.Command("USER_ERROR_HAS_IMAGE", toolStripComboBoxErrors.SelectedItem.ToString()));

            tabControlConsole.SelectTab(tabPageErrors);
            tabErrors.SelectTab(tabUserErrorErrors);
            txtUserErrorInformation.Select();
            txtUserErrorInformation.Focus();
        }
        
        #endregion Toolbar Methods

        #region Printing

        /// <summary>
        /// Prints a page
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PrintDocumentOnPrintPage(object sender, PrintPageEventArgs e)
        {
            int x = SystemInformation.WorkingArea.X;
            int y = SystemInformation.WorkingArea.Y;
            int width = this.Width;
            int height = this.Height;

            Rectangle bounds = new Rectangle(x, y, width, height);

            Point p = new Point(100, 100);

            switch (_printPage)
            {
                case 0:
                    e.Graphics.DrawString(txtUserErrorInformation.Text, txtUserErrorInformation.Font, Brushes.Black, p);
                    break;

                case 1:
                    e.Graphics.DrawString(txtUserErrorExtraInformation.Text, txtUserErrorExtraInformation.Font, Brushes.Black, p);
                    break;
            }

            e.HasMorePages = _printPage == 0;

            _printPage++;
        }

        #endregion Printing

        #region File Save

        /// <summary>
        /// Saves text to a file
        /// </summary>
        /// <param name="fileName">Filename</param>
        /// <param name="text">text to be saved</param>
        private void SaveToFile(string fileName, string text)
        {
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName, true))
            {
                file.Write(text);
            }
        }

        #endregion File Save
    }
}
